<?php
namespace app\admin\controller;

use app\common\model\CrontabModel;
use TiBeN\CrontabManager\CrontabAdapter;
use TiBeN\CrontabManager\CrontabJob;
use TiBeN\CrontabManager\CrontabRepository;

class Crontab extends Common
{
    /**
     * 添加计划任务
     * @author 贺强
     * @time   2022/10/25 18:30
     */
    public function add()
    {
        if ($this->request->isPost()) {
            if (!empty($this->admin['code'])) {
                return $this->admin;
            }
            $param = $this->request->post();
            if (empty($param['name']) || empty($param['task_code'])) {
                return ajax('参数缺失', 101);
            }
            if (!isset($param['minutes']) || $param['minutes'] === '') {
                $param['minutes'] = '*';
            }
            if (!isset($param['hours']) || $param['hours'] === '') {
                $param['hours'] = '*';
            }
            if (!isset($param['day_of_month']) || $param['day_of_month'] === '') {
                $param['day_of_month'] = '*';
            }
            if (!isset($param['month']) || $param['month'] === '') {
                $param['month'] = '*';
            }
            if (!isset($param['day_of_week']) || $param['day_of_week'] === '') {
                $param['day_of_week'] = '*';
            }
            $param['task_code'] = str_replace('+', ' ', $param['task_code']);
            try {
                $repository = new CrontabRepository(new CrontabAdapter());
                $crontabJob = new CrontabJob();
                $crontabJob->setMinutes($param['minutes'])
                    ->setHours($param['hours'])
                    ->setDayOfMonth($param['day_of_month'])
                    ->setMonths($param['month'])
                    ->setDayOfWeek($param['day_of_week'])
                    ->setTaskCommandLine($param['task_code'])
                    ->setComments($param['name']);
                // 使用原始cron语法字符串创建任务
                // $crontabJob = CrontabJob::createFromCrontabLine("* * * * * php think user >> /tmp/task.log");
                $repository->addJob($crontabJob);
                $repository->persist();
                $param['status'] = 1;
                $param['mtime'] = 0;
                $res = CrontabModel::add($param);
                if (!$res) {
                    return ajax('添加失败', 301);
                }
                return ajax('添加成功');
            } catch (\Exception $e) {
                if ($e->getCode() === 10500) {
                    return ajax('多余参数' . $e->getMessage(), 302);
                }
                return ajax('服务异常' . $e->getMessage(), $e->getCode());
            }
        }
        return view('add');
    }

    /**
     * 删除计划任务
     * @author 贺强
     * @time   2022/10/25 18:33
     */
    public function del()
    {
        if (!$this->request->isAjax()) {
            $this->error('非法操作');
        }
        try {
            if (!empty($this->admin['code'])) {
                return $this->admin;
            }
            $id = $this->request->post('id', '');
            $cron = CrontabModel::getModel(['id' => $id]);
            $regex = str_replace(' ', '\ ', $cron['task_code']);
            $regex = str_replace('/', '\/', $regex);
            $repository = new CrontabRepository(new CrontabAdapter());
            $jobs = $repository->findJobByRegex("/{$regex}/");
            $crontabJob = $jobs[0];
            $repository->removeJob($crontabJob);
            $repository->persist();
            $res = CrontabModel::delById($id);
            if (!$res) {
                return ajax('删除失败', 301);
            }
            return ajax('删除成功');
        } catch (\Exception $e) {
            return ajax($e->getMessage(), 501, $e);
        }
    }

    /**
     * 修改计划任务
     * @author 贺强
     * @time   2022/10/25 18:35
     */
    public function edit()
    {
        $id = $this->request->param('id', '');
        if ($this->request->isAjax()) {
            if (!empty($this->admin['code'])) {
                return $this->admin;
            }
            try {
                $data = $this->request->post();
                $data['task_code'] = str_replace('+', ' ', $data['task_code']);
                $regex = str_replace(' ', '\ ', $data['task_code']);
                $regex = str_replace('/', '\/', $regex);
                $repository = new CrontabRepository(new CrontabAdapter());
                $jobs = $repository->findJobByRegex("/{$regex}/");
                $crontabJob = $jobs[0];
                $crontabJob->setMinutes($data['minutes'])
                    ->setHours($data['hours'])
                    ->setDayOfMonth($data['day_of_month'])
                    ->setMonths($data['month'])
                    ->setDayOfWeek($data['day_of_week'])
                    ->setTaskCommandLine($data['task_code'])
                    ->setComments($data['name']);
                $repository->persist();
                $res = CrontabModel::modify($data, ['id' => $id]);
                if (!$res) {
                    return ajax('修改失败', 301);
                }
                return ajax('修改成功');
            } catch (\Exception $e) {
                return ajax($e->getMessage(), 501);
            }
        }
        $cron = CrontabModel::getModel(['id' => $id], true, '', 0);
        $status = [0 => '禁用', 1 => '启用'];
        return view('edit', compact('cron', 'status'));
    }

    /**
     * 计划任务列表
     * @author 贺强
     * @time   2022/10/25 17:55
     */
    public function lists()
    {
        $where = [];
        $param = $this->request->param();
        if (!empty($param['keyword'])) {
            $where[] = ['name', 'like', "%{$param['keyword']}%"];
        }
        // 分页参数
        $page = $param['page'] ?? 1;
        $pagesize = $param['pagesize'] ?? env('app.pagesize', 20);
        // 排序参数
        $order = ['ctime' => 'desc'];
        if (!empty($param['sort_field'])) {
            $order = [$param['sort_field']];
            if (!empty($param['sort_type'])) {
                $order = [$param['sort_field'] => $param['sort_type']];
            }
        }
        $list = CrontabModel::getList($where, true, [$page, $pagesize], $order);
        foreach ($list as &$item) {
            format_datetime($item['ctime']);
            format_datetime($item['mtime']);
            $item['status_txt'] = get_crontab_status($item['status'] ?? 1);
        }
        if ($this->request->isAjax()) {
            return ajax('获取成功', 200, $list);
        }
        $count = CrontabModel::getCount($where);
        $pages = ceil($count / $pagesize);
        return view('list', compact('list', 'pages', 'param', 'count'));
    }

    /**
     * 修改计划任务状态
     * @author 贺强
     * @time   2022/12/12 7:03
     */
    public function operate()
    {
        if (!empty($this->admin['code'])) {
            return $this->admin;
        }
        $ids = $this->request->post('ids');
        if (empty($ids)) {
            return ajax('非法参数', 301);
        }
        $type = $this->request->post('type');
        if (empty($type)) {
            return ajax('非法操作', 101);
        }
        if ($type === 'disable' || $type === 'disableAll') {
            $field = 'status';
            $value = 0;
            $msg = '禁用';
        } elseif ($type === 'enable' || $type == 'enableAll') {
            $field = 'status';
            $value = 1;
            $msg = '启用';
        } else {
            return ajax('非法操作', 102);
        }
        $res = CrontabModel::modify([$field => $value], [['id', 'in', $ids]]);
        if ($res) {
            return ajax($msg . '成功');
        } elseif ($res === false) {
            return ajax($msg . '失败', 400);
        } else {
            return ajax('该账号已' . $msg, 101);
        }
    }
}
